#include "../include/DataManager.hh"
#include "../include/SavingsAccount.hh"
#include "../include/CheckingAccount.hh"
#include <iostream>
#include <fstream>
#include <filesystem>
#include <sstream>

// 如果不支持 C++17 的 filesystem，可以使用其他方式
namespace fs = std::filesystem;

DataManager::DataManager(const std::string& dataDir)
    : dataDirectory(dataDir) {
    
    // 设置文件路径
    customersFilePath = dataDirectory + "customers.txt";
    accountsFilePath = dataDirectory + "accounts.txt";
    transactionsFilePath = dataDirectory + "transactions.txt";
    
    // 确保数据目录存在
    ensureDataDirectoryExists();
}

bool DataManager::saveCustomers(const std::vector<std::shared_ptr<Customer>>& customers) const {
    std::ofstream file(customersFilePath);
    if (!file.is_open()) {
        std::cerr << "无法打开文件进行写入: " << customersFilePath << std::endl;
        return false;
    }
    
    // 简单格式化：每行一个客户，格式为"username|role"
    for (const auto& customer : customers) {
        file << customer->getUsername() << "|" << static_cast<int>(customer->getRole()) << std::endl;
    }
    
    file.close();
    return true;
}

bool DataManager::saveAccounts(const std::vector<std::shared_ptr<Account>>& accounts) const {
    std::ofstream file(accountsFilePath);
    if (!file.is_open()) {
        std::cerr << "无法打开文件进行写入: " << accountsFilePath << std::endl;
        return false;
    }
    
    // 格式化：每行一个账户，格式为"accountId|ownerName|cny_balance|usd_balance|eur_balance|accountType"
    for (const auto& account : accounts) {
        std::string accountType;
        if (dynamic_cast<SavingsAccount*>(account.get())) {
            accountType = "savings";
        } else if (dynamic_cast<CheckingAccount*>(account.get())) {
            accountType = "checking";
        } else {
            accountType = "unknown";
        }
        
        // 获取各种货币的余额
        double cnyBalance = account->getBalance(Currency::CNY);
        double usdBalance = account->getBalance(Currency::USD);
        double eurBalance = account->getBalance(Currency::EUR);
        
        file << account->getAccountId() << "|" 
             << account->getOwnerName() << "|" 
             << cnyBalance << "|" 
             << usdBalance << "|" 
             << eurBalance << "|" 
             << accountType << std::endl;
    }
    
    file.close();
    return true;
}

bool DataManager::saveTransactions(const std::vector<Transaction>& transactions) const {
    std::ofstream file(transactionsFilePath);
    if (!file.is_open()) {
        std::cerr << "无法打开文件进行写入: " << transactionsFilePath << std::endl;
        return false;
    }
    
    // 格式化：每行一个交易，格式为"transactionId|type|amount|timestamp|sourceAccountId|destinationAccountId|note|currency"
    for (const auto& transaction : transactions) {
        file << transaction.transactionId << "|" 
             << static_cast<int>(transaction.type) << "|" 
             << transaction.amount << "|" 
             << transaction.timestamp << "|" 
             << transaction.sourceAccountId << "|" 
             << transaction.destinationAccountId << "|" 
             << transaction.note << "|"
             << static_cast<int>(transaction.currency) << std::endl;
    }
    
    file.close();
    return true;
}

std::vector<std::shared_ptr<Customer>> DataManager::loadCustomers() const {
    std::vector<std::shared_ptr<Customer>> customers;
    
    std::ifstream file(customersFilePath);
    if (!file.is_open()) {
        std::cerr << "无法打开文件进行读取: " << customersFilePath << std::endl;
        return customers;
    }
    
    std::string line;
    while (std::getline(file, line)) {
        std::stringstream ss(line);
        std::string username;
        int roleInt;
        
        // 解析格式："username|role"
        if (std::getline(ss, username, '|') && ss >> roleInt) {
            Role role = static_cast<Role>(roleInt);
            
            // 根据角色创建不同的用户类型
            std::shared_ptr<User> user;
            switch (role) {
                case Role::CUSTOMER:
                    customers.push_back(std::make_shared<Customer>(username));
                    break;
                // 其他角色类型的用户不在这里加载
            }
        }
    }
    
    file.close();
    return customers;
}

std::vector<std::shared_ptr<Account>> DataManager::loadAccounts(
    const std::vector<std::shared_ptr<Customer>>& customers) const {
    
    std::vector<std::shared_ptr<Account>> accounts;
    
    std::ifstream file(accountsFilePath);
    if (!file.is_open()) {
        std::cerr << "无法打开文件进行读取: " << accountsFilePath << std::endl;
        return accounts;
    }
    
    std::string line;
    while (std::getline(file, line)) {
        std::stringstream ss(line);
        std::string accountId, ownerName, accountType;
        double cnyBalance = 0.0, usdBalance = 0.0, eurBalance = 0.0;
        
        // 解析格式："accountId|ownerName|cny_balance|usd_balance|eur_balance|accountType"
        std::getline(ss, accountId, '|');
        std::getline(ss, ownerName, '|');
        
        // 尝试读取多种货币余额
        if (!(ss >> cnyBalance)) {
            cnyBalance = 0.0;
        }
        ss.ignore(); // 忽略分隔符
        
        // 检查是否有更多数据可以读取（兼容新旧格式）
        if (ss.peek() != EOF) {
            if (!(ss >> usdBalance)) {
                usdBalance = 0.0;
            }
            ss.ignore(); // 忽略分隔符
            
            if (ss.peek() != EOF) {
                if (!(ss >> eurBalance)) {
                    eurBalance = 0.0;
                }
                ss.ignore(); // 忽略分隔符
            }
        }
        
        std::getline(ss, accountType);
        
        // 创建账户
        std::shared_ptr<Account> account;
        if (accountType == "savings") {
            account = std::make_shared<SavingsAccount>(accountId, ownerName, cnyBalance);
        } else if (accountType == "checking") {
            account = std::make_shared<CheckingAccount>(accountId, ownerName, cnyBalance);
        } else {
            std::cerr << "未知账户类型: " << accountType << std::endl;
            continue;
        }
        
        // 设置其他货币余额
        if (usdBalance > 0.0) {
            account->deposit(usdBalance, Currency::USD, "初始美元余额");
        }
        if (eurBalance > 0.0) {
            account->deposit(eurBalance, Currency::EUR, "初始欧元余额");
        }
        
        accounts.push_back(account);
        
        // 将账户添加到对应的客户
        for (auto& customer : customers) {
            if (customer->getUsername() == ownerName) {
                customer->addAccount(account);
                break;
            }
        }
    }
    
    file.close();
    return accounts;
}

std::vector<Transaction> DataManager::loadTransactions() const {
    std::vector<Transaction> transactions;
    
    std::ifstream file(transactionsFilePath);
    if (!file.is_open()) {
        std::cerr << "无法打开文件进行读取: " << transactionsFilePath << std::endl;
        return transactions;
    }
    
    std::string line;
    while (std::getline(file, line)) {
        std::stringstream ss(line);
        std::string transactionId, sourceAccountId, destinationAccountId, note;
        int typeInt;
        double amount;
        time_t timestamp;
        int currencyInt = 0; // 默认为CNY
        
        std::getline(ss, transactionId, '|');
        
        if (!(ss >> typeInt)) {
            std::cerr << "读取交易类型失败: " << line << std::endl;
            continue;
        }
        ss.ignore(); // 忽略分隔符
        
        if (!(ss >> amount)) {
            std::cerr << "读取金额失败: " << line << std::endl;
            continue;
        }
        ss.ignore(); // 忽略分隔符
        
        if (!(ss >> timestamp)) {
            std::cerr << "读取时间戳失败: " << line << std::endl;
            continue;
        }
        ss.ignore(); // 忽略分隔符
        
        std::getline(ss, sourceAccountId, '|');
        std::getline(ss, destinationAccountId, '|');
        std::getline(ss, note, '|');
        
        // 尝试读取货币类型（兼容旧格式）
        if (ss.peek() != EOF) {
            if (!(ss >> currencyInt)) {
                currencyInt = 0; // 如果读取失败，默认为CNY
            }
        }
        
        TransactionType type = static_cast<TransactionType>(typeInt);
        Currency currency = static_cast<Currency>(currencyInt);
        
        // 使用带货币类型的构造函数创建交易
        Transaction transaction(transactionId, type, amount, sourceAccountId, destinationAccountId, note, currency);
        transaction.timestamp = timestamp; // 设置正确的时间戳
        
        transactions.push_back(transaction);
    }
    
    file.close();
    return transactions;
}

bool DataManager::saveAllData(const std::vector<std::shared_ptr<Customer>>& customers,
                             const std::vector<std::shared_ptr<Account>>& accounts,
                             const std::vector<Transaction>& transactions) const {
    
    bool success = true;
    
    success &= saveCustomers(customers);
    success &= saveAccounts(accounts);
    success &= saveTransactions(transactions);
    
    return success;
}

bool DataManager::loadAllData(std::vector<std::shared_ptr<Customer>>& customers,
                             std::vector<std::shared_ptr<Account>>& accounts,
                             std::vector<Transaction>& transactions) const {
    
    customers = loadCustomers();
    accounts = loadAccounts(customers);
    transactions = loadTransactions();
    
    return true;
}

bool DataManager::ensureDataDirectoryExists() const {
    try {
        if (!fs::exists(dataDirectory)) {
            return fs::create_directories(dataDirectory);
        }
        return true;
    } catch (const std::exception& e) {
        std::cerr << "创建数据目录失败: " << e.what() << std::endl;
        return false;
    }
} 